<?php

namespace App\Model;

use App\Constants\ErrorCode;
use App\Services\SmsService;
use DateTimeZone;
use Hyperf\DbConnection\Db;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\Redis\Redis;
use Phper666\JWTAuth\Util\JWTUtil;
use Psr\Container\NotFoundExceptionInterface;
use RedisException;
use Util\Common;
use Psr\Container\ContainerExceptionInterface;
use Hyperf\Di\Annotation\Inject;

class Member extends Model
{

    /**
     * @var MemberTime
     */
    #[Inject]
    protected MemberTime $memberTime;
    #[Inject]
    protected DownHistory $downHistory;

    public bool $timestamps = true;

    protected ?string $table = 'member';
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected array $fillable = [
        'id', 'username', 'nickname', 'email', 'mobile', 'avatar', 'gender', 'birthday', 'lastlogintime',
        'lastloginip', 'loginfailure', 'joinip', 'jointime', 'motto', 'password', 'status', 'bd_vid',
        'batoken', 'openid', 'is_vip', 'vip_time', 'return_status', 'Login_type', 'keyword', 'bd_userid',
        'bd_planid', 'bd_unitid', 'bd_keywordid', 'is_up'
    ];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected array $casts = [
        'created_at' => 'datetime:Y-m-d H:i:s',
        'updated_at' => 'datetime:Y-m-d H:i:s',
    ];


    /**构造登陆态内容
     * @param $info
     * @return array
     */
    public function makeInfo($info): array
    {
        $member = [];
        $member['id'] = $info->id;
        $member['mobile'] = $info->mobile;
        $member['keyword'] = $info->keyword;
        $member['openid'] = $info->openid;
        $member['nickname'] = $info->nickname;
        $member['username'] = $info->username;
        $member['userid'] = $info->bd_userid;
        $member['planid'] = $info->bd_planid;
        $member['unitid'] = $info->bd_unitid;
        $member['keywordid'] = $info->bd_keywordid;
        $member['is_vip'] = $info->is_vip;
        $member['vip_time'] = $info->vip_time;
        $member['Login_type'] = $info->Login_type;
        $member['bd_vid'] = $info->bd_vid;
        return $member;
    }

    /**获取登陆态
     * @param RequestInterface $request
     * @return array
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface|RedisException
     */
    public function getInfo(RequestInterface $request): array
    {
        $token = $request->getHeaderLine('Authorization') ?? '';
        if($token == 'Bearer null'){
            return [];
        }
        if ($token) {
            $jwtArray = JWTUtil::getParserData($request);
            if (!isset($jwtArray['id'])) {
                return [];
            }
            $jwtArray['now'] = date('Y-m-d H:i:s', time());
            if ($jwtArray) {
                $info = redis()->get(Common::MEMBER_REDIS_INFO . $jwtArray['id']);
                $memberModel = json_decode($info);
                $jwtArray['exp'] = $jwtArray['exp']->setTimezone(new DateTimeZone('Asia/Shanghai'));
                $jwtArray['exp_time'] = $jwtArray['exp']->getTimestamp();
                if (time() > $jwtArray['exp_time']) {
                    return [];
                }
                $jwtArray['is_vip'] = $memberModel->is_vip;
                $jwtArray['vip_time'] = $memberModel->vip_time;
                $jwtArray['vip_date'] = '';
                if ($jwtArray['is_vip'] && $jwtArray['vip_time']) {
                    if ($jwtArray['vip_time'] < time()) {
                        self::save(['is_vip' => 0]);
                        $jwtArray['is_vip'] = 0;
                    }
                    $jwtArray['vip_date'] = date('Y-m-d', $jwtArray['vip_time']);
                }
                $final = strtotime("2099-12-31");
                $jwtArray['final'] = 0;
                if ($jwtArray['vip_time'] >= $final) {
                    $jwtArray['final'] = 1;
                }
            }
            return $jwtArray;
        }
        return [];
    }

    /**
     * @param int $user_id
     * @param int $contract_id
     * @return bool
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function addHistory(int $user_id, int $contract_id): bool
    {
        $key = Common::HOME_HISTORY . $user_id;
        redis()->lrem($key, 0, $contract_id);
        redis()->lpush($key, $contract_id);
        redis()->ltrim($key, 0, 4);
        return true;
    }

    /**取消收藏和收藏
     * @param RequestInterface $request
     * @return array
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function collect(RequestInterface $request, string $type = 'sadd'): array
    {
        $contract_id = $request->input('contract_id');
        $member = $this->getInfo($request);
        if (!$member) {
            return array('code' => ErrorCode::UNKNOW_INFO);
        }
        if (!$contract_id) {
            return array('code' => ErrorCode::PARAMS_ERR);
        }
        $key = Common::MEMBER_COLLECT . $member['id'];
        $isExist = redis()->sismember($key, $contract_id);
        if ($type == 'sadd') {
            if ($isExist) {
                return array('code' => ErrorCode::COLLECT_ERR);
            }
            redis()->sadd($key, $contract_id);
        } else {
            if (!$isExist) {
                return array('code' => ErrorCode::UN_COLLECT_ERR);
            }
            redis()->srem($key, $contract_id);
        }
        return array('code' => ErrorCode::SUCCESS);
    }

    /**获取用户收藏列表
     * @param RequestInterface $request
     * @return array
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function collectList(RequestInterface $request): array
    {
        $member = $this->getInfo($request);
        if (!$member) {
            return array('code' => ErrorCode::UNKNOW_INFO);
        }
        $key = Common::MEMBER_COLLECT . $member['id'];
        $list = redis()->smembers($key);
        if ($list) {
            return Contract::whereIn('id', $list)->get(['id', 'title', 'title_pic'])->toArray();
        }
        return [];
    }


    /**获取用户是否收藏合同
     * @param int $memberId
     * @param int $contractId
     * @return bool
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function isCollect(int $memberId, int $contractId): bool
    {
        $collect_key = Common::MEMBER_COLLECT . $memberId;
        $collect_list = redis()->smembers($collect_key);
        if ($collect_list && in_array($contractId, $collect_list)) {
            return true;
        }
        return false;
    }

    /**获取浏览历史
     * @param $memberId
     * @return array
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function getHistory($memberId): array
    {
        $key = 'HOME_HISTORY_' . $memberId;
        return redis()->lrange($key, 0, 4);
    }

    /**获取下载历史
     * @param array $page
     * @param int $memberId
     * @return array
     */
    public function getDownHistory(array $page, int $memberId): array
    {
        if ($page['type'] == 2) {
            $data['data'] = Db::table('down_history as h')
                ->leftJoin('special as s', 'h.special_id', '=', 's.id')
                ->where('h.member_id', $memberId)
                ->where('h.type', $page['type'])
                ->offset(($page['page'] - 1) * $page['limit'])
                ->limit($page['limit'])
                ->orderBy('h.id', 'desc')
                ->select('s.title', 's.image', 'h.created_at', 's.id', 's.zip', 'h.type')
                ->get();
        } else {
            $page['type'] = 1;
            $data['data'] = Db::table('down_history as h')
                ->leftJoin('contract as c', 'h.contract_id', '=', 'c.id')
                ->where('h.member_id', $memberId)
                ->where('h.type', $page['type'])
                ->offset(($page['page'] - 1) * $page['limit'])
                ->limit($page['limit'])
                ->orderBy('h.id', 'desc')
                ->select('c.title', 'c.title_pic', 'h.created_at', 'c.id', 'c.path', 'h.type')
                ->get();
        }
        $data['count'] = Db::table('down_history')
            ->where('member_id', $memberId)
            ->where('type', $page['type'])
            ->count();
        return $data;
    }

    /**用户当天剩余下载量
     * @param int $memberId
     * @param $now
     * @return int
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function getDownNum(int $memberId, $now, bool $decr = false): int
    {
        $down_count = 0;
        $list = MemberTime::where('member_id', $memberId)
            ->where('end', '>', $now)
            ->orderBy('down_count', 'desc')
            ->first();
        if ($list) {
            $down_count = $list->down_count ?? 0;
        }
        $today = date('Y-m-d', $now);
        $key = "MEMBER_DOWN_" . $today . '_' . $memberId;
        if (!redis()->exists($key)) {
            $count = $down_count;
            redis()->setex($key, 60 * 60 * 24, $down_count);
        } else {
            $count = redis()->get($key);
            if ($count <= 0) {
                $today_down_count = DownHistory::where('member_id', $memberId)
                    ->where('created_at', '>', $today . ' 00:00:00')
                    ->where('created_at', '<', $today . '23:59:59')
                    ->count();
                $count = $down_count - $today_down_count;
                if ($count > 0) {
                    redis()->setex($key, 60 * 60 * 24, $count);
                } else {
                    $count = 0;
                }
            }
        }
        if ($count > 0 && $decr) {
            redis()->decr($key);
        }
        return $count;
    }

    /**获取升级会员的差价
     * @param int $memberId
     * @return array
     */
    public function getBuyPrice(int $memberId): array
    {
        $data['buy_price'] = Order::where('member_id', $memberId)
            ->where('type', OrderType::NORMAL_TYPE)
            ->where('status', Order::PAYED)
            ->sum('money');
        $data['all_price'] = OrderType::where('tag', '终身会员')
            ->where('is_del', Common::DEL_SHOW)
            ->value('price');
        return $data;
    }

    /**升级会员
     * @param int $memberId
     * @param $now
     * @param string $order_sn
     * @return bool
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public static function upVip(int $memberId, $now, string $order_sn = ''): bool
    {

        $model = MemberTime::where('member_id', $memberId)
            ->where('start', '<', $now)
            ->where('end', '>=', $now)
            ->orderBy('down_count', 'desc')
            ->first();
        $getType = OrderType::where('tag', '终身会员')->first();
        $vip_time = strtotime(date("Y-m-d H:i:s", strtotime("+{$getType->days} day")));
        $info = [];
        try {
            if ($model) {
                $model->start = time();
                $model->end = $vip_time;
                $tempCount = $model->down_count;
                $model->down_count = $getType->count;
                if ($order_sn) {
                    $model->order_id = $order_sn;
                }
                $model->member_id = $memberId;
                $today = date('Y-m-d', $now);
                $key = "MEMBER_DOWN_" . $today . '_' . $memberId;
                if ($model->save()) {
                    $info = Member::where('id', $memberId)->first();
                    $info->is_vip = Common::MEMBER_VIP;
                    $info->vip_time = $vip_time;
                    $info->save();
                }
                if (!redis()->exists($key)) {
                    redis()->setex($key, 60 * 60 * 24, $getType->count);
                } else {
                    $now_count = redis()->get($key);
                    $use_count = $tempCount - $now_count;
                    $set_count = $getType->count - $use_count;
                    if ($set_count < 0) {
                        $set_count = 0;
                    }
                    redis()->setex($key, 60 * 60 * 24, $set_count);
                }
            } else {
                $save['start'] = time();
                $save['end'] = $vip_time;
                $save['down_count'] = $getType->count;
                $save['member_id'] = $memberId;
                if ($order_sn) {
                    $save['order_id'] = $order_sn;
                }
                $today = date('Y-m-d', $now);
                $key = "MEMBER_DOWN_" . $today . '_' . $memberId;
                redis()->setex($key, 60 * 60 * 24, $getType->count);
                MemberTime::create($save);
                $info = Member::where('id', $memberId)->first();
                $info->is_vip = Common::MEMBER_VIP;
                $info->vip_time = $vip_time;
                $info->save();
            }
            if (redis()->exists(Common::MEMBER_REDIS_INFO . $memberId)) {
                redis()->getSet(Common::MEMBER_REDIS_INFO . $memberId, json_encode($info));
            }
            return true;
        } catch (\Exception $e) {
            return false;
        }
    }

    /**百度回传
     * @param $bd_vid
     * @param $type
     * @return bool
     */

    public static function baiduOcpc($bd_vid, $type): bool
    {
        try {
            $ocpc_config = config('baidu');
            if (!$ocpc_config['token']) {
                return false;
            }
            if (!$bd_vid) {
                return false;
            }
            $token = $ocpc_config['token'];
            $origin = 'https://mihetong.com';
            $logidUrl = $origin . '?bd_vid=' . $bd_vid;
            $cv = [
                'logidUrl' => $logidUrl, // 您的落地页url
                'newType' => $type, // 转化类型请按实际情况填写    //35-微信复制按钮点击  20-深度页面访问
                'convertTime' => time(),
                'isConvert' => 1,
                'confidence' => 100,
            ];
            $conversionTypes = array($cv);
            $api_url = 'https://ocpc.baidu.com/ocpcapi/api/uploadConvertData';
            $reqData = array('token' => $token, 'conversionTypes' => $conversionTypes);
            // $reqData = json_encode($reqData);
            $res = httpPostRequest($api_url, $reqData);
            $res = json_decode($res, true);
            $userModel = Member::where('bd_vid', $bd_vid)->first();
            if ($res['header']['status'] == 0) {
                $userModel->return_status = 1;
                $userModel->save();
            }
            OcpcReturn::create([
                'member_id' => $userModel->id ?? 0,
                'type' => $type,
                'bd_vid' => $bd_vid,
                'result' => json_encode($res),
                'post_data' => json_encode($cv)
            ]);
            return true;
        } catch (\Exception $e) {
            return false;
        }
    }
}
